package cn.wolfcode.shop.cloud.web.controller;

import cn.wolfcode.shop.cloud.common.AssertUtil;
import cn.wolfcode.shop.cloud.common.CookieUtils;
import cn.wolfcode.shop.cloud.common.Result;
import cn.wolfcode.shop.cloud.domain.OrderInfo;
import cn.wolfcode.shop.cloud.redis.key.SeckillRedisKey;
import cn.wolfcode.shop.cloud.service.IOrderInfoService;
import cn.wolfcode.shop.cloud.web.msg.SeckillServerCodeMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by wolfcode-lanxw
 */
@RestController
@RequestMapping("/api/seckill/orders")
public class OrderInfoController {

    /**
     * 本地售完标记map
     * key=秒杀商品id
     * value=是否已经售完
     */
    public static final ConcurrentHashMap<Long, Boolean> STOCK_OVER_FLAG_MAP = new ConcurrentHashMap<>();

    @Autowired
    private IOrderInfoService orderInfoService;

    /**
     * 秒杀压力测试:
     *  优化前:
     *      请求数: 100 * 50
     *      吞吐量: QPS: 714.2/s
     *  优化后:
     *      请求数: 100 * 50
     *      吞吐量: QPS: 2207.5/s
     *
     * @param token
     * @param seckillId
     * @return
     */
    @PostMapping("/{random}")
    public Result<String> doSeckill(@CookieValue(name = CookieUtils.USER_IN_TOKEN) String token,
                                    @PathVariable("random") String random, String uuid, Long seckillId) {
        Boolean flag = STOCK_OVER_FLAG_MAP.get(seckillId);
        // 本地售完标记判断, 如果 flag 为空或者 flag 为 false 表示可以进行秒杀,否则直接抛出
        AssertUtil.isTrue(flag == null || !flag, SeckillServerCodeMsg.OUT_OF_STOCK_ERROR);
        // 开始进行秒杀
        orderInfoService.doSeckill(seckillId, uuid, token, random);
        // 异步下单, 返回正在下单中
        return Result.success("正在下单中..");
    }

    @GetMapping("/{orderNo}")
    public Result<OrderInfo> detail(@PathVariable("orderNo") String orderNo, @CookieValue(name = CookieUtils.USER_IN_TOKEN) String token) {
        OrderInfo orderInfo = orderInfoService.findById(orderNo, token);
        return Result.success(orderInfo);
    }
}
